ChristmasError-Blog

C++11 Lambda表达式

字数统计: 1.1k阅读时长: 4 min
2018/10/21 Share

Lambda表达式

匿名函数有函数体,但没有函数名。
匿名函数是很多高级语言都支持的概念,如lisp语言在1958年首先采用匿名函数。正因为如此,C++11也同样引入了lambda函数。
在C++11中,你可以在源码中内联一个lambda函数,这就使得创建快速的、一次性的函数变得简单了。

相同类似功能我们也可以使用函数对象或者函数指针实现:函数对象能维护状态,但语法开销大,而函数指针语法开销小,却没法保存范围内的状态。lambda表达式正是结合了两者的优点。

声明Lambda表达式

1
2
3
4
[capture list] (params list) mutable exception-> return type { function body };
[capture list] (params list) -> return type {function body}; //1
[capture list] (params list) {function body}; //2
[capture list] {function body}; //3
  • capture list:捕获外部变量列表
  • params list:形参列表
  • mutable指示符:用来说用是否可以修改捕获的变量
  • exception:异常设定
  • return type:返回类型
  • function body:函数体

    标号1. 函数声明了一个const类型的表达式,此声明不可改变capture list中的捕获的值。
    标号2. 函数省略了返回值,此时如果function body内含有return语句,则按return语句返回类型决定返回值类型,若无则返回值为void类型。
    标号3. 函数无参数列表,意味无参函数。

    简单的例子

    在C++中我们对STL库中的sort()运用十分频繁,接下来就是关于他的一个例子:

1
2
3
4
5
6
7
8
9
//省略细节
bool compare(int a,int b){
return a<b;
}
{
vector<int> vec{1,0,9,5,3,3,7,8,2};
sort(vec.begin(),vec.end(),compare);
//在C++11之前,我们使用STL的sort函数,可以提供一个谓词函数来为sort改变其排序判断标准
}

接下来是lambda表达式的形式:

1
2
3
4
5
{	
vector<int> vec{1,0,9,5,3,3,7,8,2};
sort(lbvec.begin(), lbvec.end(), [](int a, int b) -> bool { return a < b; });
// Lambda表达式
}

lambda不仅提高了代码可读性,且在例子中,这一个提供判断依据的函数是只需调用一次,在这时,lambda表达式就显示出它的“即用即扔”的特点,很适合这种不需要重复调用且运用区域单一的情景(而不是去多写一个compare的函数)。

捕获外部变量

Lambda表达式可以捕获外面变量,但需要我们提供一个谓词函数([capture list]在声明表达式最前)
类似参数传递方式:值传递、引入传递、指针传递。
在Lambda表达式中,外部变量捕获方式也类似:值捕获、引用捕获、隐式捕获

值捕获

1
2
3
4
5
int a = 123;
auto f = [a] { cout << a << endl; };
f(); // 输出:123
a = 321;
f(); // 输出:123

值捕获和参数传递中的值传递类似,被捕获的值在Lambda表达式创建时通过值拷贝的方式传入,因此Lambda表达式函数体中不能修改该外部变量的值;同样,函数体外对于值的修改也不会改变被捕获的值。

引用捕获

1
2
3
4
int a = 123;
auto f = [&a] { cout << a << endl; };
a = 321;
f(); // 输出:321

引用捕获的变量使用的实际上就是该引用所绑定的对象,因此引用对象的改变会改变函数体内对该对象的引用的值。

隐式捕获

隐式捕获有两种方式,分别是
[=]:以值补获的方式捕获外部所有变量
[&]:表示以引用捕获的方式捕获外部所有变量

1
2
3
int a = 123 ,b=321;
auto df = [=] { cout << a << b << endl; }; // 值捕获
auto rf = [&] { cout << a << b << endl; }; // 引用捕获

其他捕获方式

C++11Lambda表达式捕获外部变量形式
[ ] 不捕获任何变量(无参函数)
[变量1,&变量2, …] 值(引用)形式捕获指定的多个外部变量
[this] 值捕获this指针
[=, &x] 变量x以引用形式捕获,其余变量以传值形式捕获

Lambda表达式的参数

  • 参数列表中不能有默认参数
  • 不支持可变参数
  • 所有参数必须有参数名
CATALOG
  1. 1. Lambda表达式
    1. 1.1. 声明Lambda表达式
      1. 1.1.1. 简单的例子
    2. 1.2. 捕获外部变量
      1. 1.2.1. 值捕获
      2. 1.2.2. 引用捕获
      3. 1.2.3. 隐式捕获
      4. 1.2.4. 其他捕获方式
    3. 1.3. Lambda表达式的参数